package com.mathassistant.client;

import java.util.ArrayList;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.SimpleEventBus;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Window;
import com.mathassistant.client.event.ShowAboutDialogEvent;
import com.mathassistant.client.event.ShowAboutDialogEventHandler;
import com.mathassistant.client.event.ShowEditorEvent;
import com.mathassistant.client.event.ShowEditorEventHandler;
import com.mathassistant.client.event.ShowLoginDialogEvent;
import com.mathassistant.client.event.ShowLoginDialogEventHandler;
import com.mathassistant.client.event.ShowTopicPopupEvent;
import com.mathassistant.client.event.ShowTopicPopupEventHandler;
import com.mathassistant.client.event.ToAdminViewEvent;
import com.mathassistant.client.event.ToAdminViewEventHandler;
import com.mathassistant.client.event.ToUserViewEvent;
import com.mathassistant.client.event.ToUserViewEventHandler;
import com.mathassistant.client.event.TopicPopupEditEvent;
import com.mathassistant.client.event.TopicPopupEditEventHandler;
import com.mathassistant.client.event.exercise.ExerciseAddEvent;
import com.mathassistant.client.event.exercise.ExerciseAddEventHandler;
import com.mathassistant.client.event.exercise.ExerciseBackNextEvent;
import com.mathassistant.client.event.exercise.ExerciseBackNextEventHandler;
import com.mathassistant.client.event.exercise.ExerciseDeletedEvent;
import com.mathassistant.client.event.exercise.ExerciseDeletedEventHandler;
import com.mathassistant.client.event.exercise.ExerciseEditEvent;
import com.mathassistant.client.event.exercise.ExerciseEditEventHandler;
import com.mathassistant.client.event.exercise.ExerciseEditFinishedEvent;
import com.mathassistant.client.event.exercise.ExerciseEditFinishedEventHandler;
import com.mathassistant.client.event.theory.TheoryDeletedEvent;
import com.mathassistant.client.event.theory.TheoryDeletedEventHandler;
import com.mathassistant.client.event.theory.TheoryEditEvent;
import com.mathassistant.client.event.theory.TheoryEditEventHandler;
import com.mathassistant.client.event.theory.TheoryEditFinisdedEvent;
import com.mathassistant.client.event.theory.TheoryEditFinishedEventHandler;
import com.mathassistant.client.event.topic.TopicAddEvent;
import com.mathassistant.client.event.topic.TopicAddEventHandler;
import com.mathassistant.client.event.topic.TopicChoosedEvent;
import com.mathassistant.client.event.topic.TopicChoosedEventHandler;
import com.mathassistant.client.presenter.AboutPresenter;
import com.mathassistant.client.presenter.DefaultContentPresenter;
import com.mathassistant.client.presenter.EditorPresenter;
import com.mathassistant.client.presenter.ExerciseEditPresenter;
import com.mathassistant.client.presenter.ExerciseManagementPresenter;
import com.mathassistant.client.presenter.ExercisePresenter;
import com.mathassistant.client.presenter.ExerciseStepEditPresenter;
import com.mathassistant.client.presenter.ExerciseStepPresenter;
import com.mathassistant.client.presenter.FooterPresenter;
import com.mathassistant.client.presenter.LoginPresenter;
import com.mathassistant.client.presenter.Presenter;
import com.mathassistant.client.presenter.TheoryPresenter;
import com.mathassistant.client.presenter.TitleContentPresenter;
import com.mathassistant.client.presenter.TopicEditPresenter;
import com.mathassistant.client.presenter.TopicListPresenter;
import com.mathassistant.client.presenter.TopicPopupPresenter;
import com.mathassistant.client.service.ExerciseService;
import com.mathassistant.client.service.ExerciseServiceAsync;
import com.mathassistant.client.service.MyUserService;
import com.mathassistant.client.service.MyUserServiceAsync;
import com.mathassistant.client.service.TheoryService;
import com.mathassistant.client.service.TheoryServiceAsync;
import com.mathassistant.client.service.TopicService;
import com.mathassistant.client.service.TopicServiceAsync;
import com.mathassistant.client.view.AboutView;
import com.mathassistant.client.view.DefaultContentView;
import com.mathassistant.client.view.EditorView;
import com.mathassistant.client.view.ExerciseEditView;
import com.mathassistant.client.view.ExerciseManagementView;
import com.mathassistant.client.view.ExerciseStepEditView;
import com.mathassistant.client.view.ExerciseStepView;
import com.mathassistant.client.view.ExerciseView;
import com.mathassistant.client.view.FooterView;
import com.mathassistant.client.view.LoginView;
import com.mathassistant.client.view.TheoryView;
import com.mathassistant.client.view.TitleContentView;
import com.mathassistant.client.view.TopicEditView;
import com.mathassistant.client.view.TopicListView;
import com.mathassistant.client.view.TopicPopupView;
import com.mathassistant.shared.Constant;

public class AppController implements ValueChangeHandler<String> {

	private final SimpleEventBus eventBus;
	private final MyUserServiceAsync rpcUserService = GWT
			.create(MyUserService.class);
	private final TopicServiceAsync rpcTopicService = GWT
			.create(TopicService.class);
	private final ExerciseServiceAsync rpcExerciseService = GWT
			.create(ExerciseService.class);
	private final TheoryServiceAsync rpcTheoryService = GWT
			.create(TheoryService.class);

	private final MathAssistantMVP container;

	Presenter footpresenter;
	Presenter contentPresenter;
	Presenter titleContentPresenter;
	Presenter topicTheoryGeometryPresenter;
	Presenter topicStepExerciseGeometryPresenter;
	Presenter topicTestExerciseGeometryPresenter;
	Presenter topicTheoryAlgebraPresenter;
	Presenter topicStepExerciseAlgebraPresenter;
	Presenter topicTestExerciseAlgebraPresenter;
	Presenter topicFinalTestPresenter;

	public AppController(SimpleEventBus eventBus, MathAssistantMVP container) {
		this.eventBus = eventBus;
		this.container = container;
		bind();
	}

	private void bind() {
		History.addValueChangeHandler(this);

		// Show about dialog event
		eventBus.addHandler(ShowAboutDialogEvent.TYPE,
				new ShowAboutDialogEventHandler() {
					@Override
					public void onShowAboutDialog(ShowAboutDialogEvent event) {
						AboutPresenter presenter = new AboutPresenter(
								new AboutView());
						presenter.go();
					}
				});

		// Show login dialog event
		eventBus.addHandler(ShowLoginDialogEvent.TYPE,
				new ShowLoginDialogEventHandler() {
					@Override
					public void onShowLoginDialog(ShowLoginDialogEvent event) {
						Presenter presenter = new LoginPresenter(
								rpcUserService, eventBus, new LoginView());
						presenter.go();
					}
				});

		// Show add topic dialog
		eventBus.addHandler(TopicAddEvent.TYPE, new TopicAddEventHandler() {
			@Override
			public void onTopicAddDSEvent(TopicAddEvent event) {
				doAddTopic(event);
			}
		});

		// show topic popup
		eventBus.addHandler(ShowTopicPopupEvent.TYPE,
				new ShowTopicPopupEventHandler() {

					@Override
					public void OnShowTopicPopup(ShowTopicPopupEvent event) {
						Presenter topicPopupPresenter = new TopicPopupPresenter(
								event.getTopic(), rpcTopicService, eventBus,
								new TopicPopupView(event.getTopic()
										.getContent(), event.getPoint()));
						topicPopupPresenter.go();
					}
				});

		eventBus.addHandler(TopicPopupEditEvent.TYPE,
				new TopicPopupEditEventHandler() {

					@Override
					public void onTopicPopupEdit(TopicPopupEditEvent event) {
						Presenter topicEditPresenter = new TopicEditPresenter(
								event.getTopic(),
								rpcTopicService,
								eventBus,
								new TopicEditView(event.getTopic().getContent()));
						topicEditPresenter.go();
					}
				});

		eventBus.addHandler(TopicChoosedEvent.TYPE,
				new TopicChoosedEventHandler() {

					@Override
					public void onTopicChoosed(TopicChoosedEvent event) {
						// TODO create exercise presenter
						doChooseTopic(event);
					}
				});

		eventBus.addHandler(ShowEditorEvent.TYPE, new ShowEditorEventHandler() {

			@Override
			public void onShowEditor(ShowEditorEvent event) {
				// TODO Auto-generated method stub
				Presenter editorPresenter = new EditorPresenter(event
						.getParent(), new EditorView(true));
				editorPresenter.go();
			}
		});

		eventBus.addHandler(ToAdminViewEvent.TYPE,
				new ToAdminViewEventHandler() {

					@Override
					public void onTopicListToAdminView(ToAdminViewEvent event) {
						// TODO Auto-generated method stub
						container.setIsLogin(true);
					}
				});

		eventBus.addHandler(ToUserViewEvent.TYPE, new ToUserViewEventHandler() {

			@Override
			public void onTopicListToUserView(ToUserViewEvent event) {
				// TODO Auto-generated method stub
				container.setIsLogin(false);
			}
		});

		eventBus.addHandler(ExerciseAddEvent.TYPE,
				new ExerciseAddEventHandler() {

					@Override
					public void onAddExercise(ExerciseAddEvent event) {
						// TODO Auto-generated method stub
						doAddExercise(event);
					}
				});

		eventBus.addHandler(ExerciseEditFinishedEvent.TYPE,
				new ExerciseEditFinishedEventHandler() {

					@Override
					public void onEditExercise(ExerciseEditFinishedEvent event) {
						// TODO Auto-generated method stub
						contentPresenter = new ExerciseManagementPresenter(
								event.getTopic(), event.getIndexExercise(),
								rpcExerciseService, eventBus,
								new ExerciseManagementView());
						contentPresenter.go(container.getContentView());
					}
				});
		eventBus.addHandler(TheoryEditFinisdedEvent.TYPE,
				new TheoryEditFinishedEventHandler() {

					@Override
					public void onEditTheoryFinished(
							TheoryEditFinisdedEvent event) {
						// TODO Auto-generated method stub
//						contentPresenter = new TheoryManagementPresenter(event
//								.getTopic(), event.getIndexBeginList(),
//								rpcTheoryService, eventBus,
//								new TheoryManagementView());
//						contentPresenter.go(container.getContentView());
					}
				});
		eventBus.addHandler(TheoryDeletedEvent.TYPE,
				new TheoryDeletedEventHandler() {

					@Override
					public void onFinishedDelete(TheoryDeletedEvent event) {
						// TODO Auto-generated method stub
//						contentPresenter = new TheoryManagementPresenter(event
//								.getTopic(), event.getIndexBeginList(),
//								rpcTheoryService, eventBus,
//								new TheoryManagementView());
//						contentPresenter.go(container.getContentView());
					}
				});
		eventBus.addHandler(TheoryEditEvent.TYPE, new TheoryEditEventHandler() {

			@Override
			public void onEditTheory(TheoryEditEvent event) {
				// TODO Auto-generated method stub
//				contentPresenter = new TheoryEditPresenter(event.getTopic(),
//						event.getTheory(), event.getIndexBeginList(),
//						rpcTheoryService, eventBus, new TheoryEditView());
//				contentPresenter.go(container.getContentView());
			}
		});
		eventBus.addHandler(ExerciseEditEvent.TYPE,
				new ExerciseEditEventHandler() {

					@Override
					public void onEditExercise(ExerciseEditEvent event) {
						// TODO Auto-generated method stub
						if (event.getTopic().getContentType()
								.equals(Constant.TEST_EXERCISE)) {
							contentPresenter = new ExerciseEditPresenter(event
									.getExercise(), event.getTopic(), event
									.getIndexBeginList(), rpcExerciseService,
									eventBus, new ExerciseEditView(null));
						} else if (event.getTopic().getContentType()
								.equals(Constant.STEP_EXERCISE)) {
							contentPresenter = new ExerciseStepEditPresenter(
									event.getExercise(), event.getTopic(),
									event.getIndexBeginList(),
									rpcExerciseService, eventBus,
									new ExerciseStepEditView());
						}
						contentPresenter.go(container.getContentView());
					}
				});

		eventBus.addHandler(ExerciseBackNextEvent.TYPE,
				new ExerciseBackNextEventHandler() {

					@Override
					public void onBackNext(ExerciseBackNextEvent event) {
						// TODO Auto-generated method stub
						doBackNext(event);
					}
				});

		eventBus.addHandler(ExerciseDeletedEvent.TYPE,
				new ExerciseDeletedEventHandler() {

					@Override
					public void onDeleteExercise(ExerciseDeletedEvent event) {
						// TODO Auto-generated method stub
						contentPresenter = new ExerciseManagementPresenter(
								event.getTopic(), event.getIndexBeginList(),
								rpcExerciseService, eventBus,
								new ExerciseManagementView());
						contentPresenter.go(container.getContentView());
					}
				});

	}

	protected void doBackNext(ExerciseBackNextEvent event) {
		// TODO Auto-generated method stub
		if (event.getTopic().getContentType().equals(Constant.STEP_EXERCISE)
				|| event.getTopic().getContentType()
						.equals(Constant.TEST_EXERCISE)) {
			contentPresenter = new ExerciseManagementPresenter(
					event.getTopic(), event.getIndexCurBeginList(),
					rpcExerciseService, eventBus, new ExerciseManagementView());
		} else if (event.getTopic().getContentType().equals(Constant.THEORY)) {
//			contentPresenter = new TheoryManagementPresenter(event.getTopic(),
//					event.getIndexCurBeginList(), rpcTheoryService, eventBus,
//					new TheoryManagementView());
		}

		contentPresenter.go(container.getContentView());
	}

	protected void doAddExercise(ExerciseAddEvent event) {
		// TODO Auto-generated method stub
		if (event.getTopic().getContentType().equals(Constant.TEST_EXERCISE)) {
			contentPresenter = new ExerciseEditPresenter(null,
					event.getTopic(), event.getIndexCurBeginList(),
					rpcExerciseService, eventBus, new ExerciseEditView(null));
			contentPresenter.go(container.getContentView());
		} else if (event.getTopic().getContentType()
				.equals(Constant.STEP_EXERCISE)) {
			contentPresenter = new ExerciseStepEditPresenter(null,
					event.getTopic(), event.getIndexCurBeginList(),
					rpcExerciseService, eventBus, new ExerciseStepEditView());
			contentPresenter.go(container.getContentView());
		} else if (event.getTopic().getContentType().equals(Constant.THEORY)) {
//			contentPresenter = new TheoryEditPresenter(event.getTopic(), null,
//					event.getIndexCurBeginList(), rpcTheoryService, eventBus,
//					new TheoryEditView());
//			contentPresenter.go(container.getContentView());
		}
	}

	protected void doAddTopic(TopicAddEvent event) {
		// TODO Auto-generated method stub
		TopicEditPresenter presenter = new TopicEditPresenter(null,
				event.getArea(), event.getContentType(), rpcTopicService,
				eventBus, new TopicEditView());
		presenter.go();
	}

	protected void doChooseTopic(TopicChoosedEvent event) {
		if (container.getIsLogin()) {
			if (event.getTopic().getContentType()
					.equals(Constant.TEST_EXERCISE)) {
				contentPresenter = new ExerciseManagementPresenter(
						event.getTopic(), 0, rpcExerciseService, eventBus,
						new ExerciseManagementView());
				contentPresenter.go(container.getContentView());
			} else if (event.getTopic().getContentType()
					.equals(Constant.STEP_EXERCISE)) {
				contentPresenter = new ExerciseManagementPresenter(
						event.getTopic(), 0, rpcExerciseService, eventBus,
						new ExerciseManagementView());
				contentPresenter.go(container.getContentView());
			} else if (event.getTopic().getContentType()
					.equals(Constant.THEORY)) {
//				contentPresenter = new TheoryManagementPresenter(
//						event.getTopic(), 0, rpcTheoryService, eventBus,
//						new TheoryManagementView());
//				contentPresenter.go(container.getContentView());
			} else {
				Window.alert("You are choosing " + event.getTopic().getArea()
						+ " and " + event.getTopic().getContentType() + "!");
			}

		} else {
			if (event.getTopic().getContentType()
					.equals(Constant.TEST_EXERCISE)) {
				contentPresenter = new ExercisePresenter(event.getTopic(),
						rpcExerciseService, eventBus, new ExerciseView());
				contentPresenter.go(container.getContentView());

			} else if (event.getTopic().getContentType()
					.equals(Constant.STEP_EXERCISE)) {
				// test StepExercise
				contentPresenter = new ExerciseStepPresenter(event.getTopic(),
						rpcExerciseService, eventBus, new ExerciseStepView());
				contentPresenter.go(container.getContentView());
			} else if (event.getTopic().getContentType()
					.equals(Constant.THEORY)) {
				contentPresenter = new TheoryPresenter(event.getTopic(), rpcTheoryService, eventBus, new TheoryView());
				contentPresenter.go(container.getContentView());
			} else {
				Window.alert("You are choosing " + event.getTopic().getArea()
						+ " and " + event.getTopic().getContentType() + "!");
			}

		}
	}

	@Override
	public void onValueChange(ValueChangeEvent<String> event) {
		String token = event.getValue();

		if (token != null) {
			if (token.equals("main")) {

				initPresenterFooter();

				initPresenterTopic();

				initPresenterContent();

				initPresenterTitleContent();

				eventBus.fireEvent(new ToUserViewEvent());

			} else if (token.equals("editExercise")) {
				// lam j nhi ^^
			} else if (token.equals("listExercises")) {
				// lam j nhi ^^
			} else if (token.equals("doExercise")) {
				// lam j nhi ^
			} else if (token.equals("test1")) {
				contentPresenter = new ExerciseStepEditPresenter(null, null, 0,
						rpcExerciseService, eventBus,
						new ExerciseStepEditView());
				contentPresenter.go(container.getContentView());
			} else if (token.equals("test")) {
				ExerciseStepView view = new ExerciseStepView();

				ArrayList<String> listAnswer = new ArrayList<String>();
				listAnswer.add("AAAAAAAAAAAAAAAA");
				listAnswer.add("BBBBBBBBBBBBBBBBBB");
				listAnswer.add("CCCCCCCCCCCCC");
				listAnswer.add("DDDDDDDDDDDDDDDD");
				listAnswer.add("EEEEEEEEEEEEEEEEe");
				view.setData(listAnswer);

				container.getContentView().setWidget(view);

			}

		}
	}

	public void go() {
		if ("".equals(History.getToken())) {
			History.newItem("main");
		} else {
			History.fireCurrentHistoryState();
		}
	}

	private void initPresenterFooter() {
		footpresenter = new FooterPresenter(eventBus, new FooterView());
		footpresenter.go(container.getFooterView());
	}

	private void initPresenterTopic() {
		topicTheoryAlgebraPresenter = new TopicListPresenter(Constant.ALGEBRA,
				Constant.THEORY, rpcTopicService, eventBus, new TopicListView());
		topicTheoryAlgebraPresenter.go(container.getTopicView()
				.getAlgebraTheoryPanel());

		topicStepExerciseAlgebraPresenter = new TopicListPresenter(
				Constant.ALGEBRA, Constant.STEP_EXERCISE, rpcTopicService,
				eventBus, new TopicListView());
		topicStepExerciseAlgebraPresenter.go(container.getTopicView()
				.getAlgebraStepExercisePanel());

		topicTestExerciseAlgebraPresenter = new TopicListPresenter(
				Constant.ALGEBRA, Constant.TEST_EXERCISE, rpcTopicService,
				eventBus, new TopicListView());
		topicTestExerciseAlgebraPresenter.go(container.getTopicView()
				.getAlgebraTestExercisePanel());

		topicTheoryGeometryPresenter = new TopicListPresenter(
				Constant.GEOMETRY, Constant.THEORY, rpcTopicService, eventBus,
				new TopicListView());
		topicTheoryGeometryPresenter.go(container.getTopicView()
				.getGeometryTheoryPanel());

		topicStepExerciseGeometryPresenter = new TopicListPresenter(
				Constant.GEOMETRY, Constant.STEP_EXERCISE, rpcTopicService,
				eventBus, new TopicListView());
		topicStepExerciseGeometryPresenter.go(container.getTopicView()
				.getGeometryStepExercisePanel());

		topicTestExerciseGeometryPresenter = new TopicListPresenter(
				Constant.GEOMETRY, Constant.TEST_EXERCISE, rpcTopicService,
				eventBus, new TopicListView());
		topicTestExerciseGeometryPresenter.go(container.getTopicView()
				.getGeometryTestExercisePanel());

		topicFinalTestPresenter = new TopicListPresenter(Constant.FINAL_TEST,
				"", rpcTopicService, eventBus, new TopicListView());
		topicFinalTestPresenter
				.go(container.getTopicView().getFinalTestPanel());
	}

	private void initPresenterContent() {
		contentPresenter = new DefaultContentPresenter(new DefaultContentView());
		contentPresenter.go(container.getContentView());
	}

	private void initPresenterTitleContent() {
		titleContentPresenter = new TitleContentPresenter(null, eventBus,
				new TitleContentView());
		titleContentPresenter.go(container.getTitleContentView());
	}
}
